package battleGame;
import java.awt.Image;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import battleGame.Army.WarriorCommand;

public abstract class Warrior extends GameObject
{
	
	int hp;
	Vector2 lookAt;
	double speed;
	int busyTime;
	double attackRadius;
	int attackDamage;
	double attackTime;
	double waitTime;
	double sightDistance;
	int team;
	Image icon;
	WarriorAction.Action currentAction;
	List< AStarNode > listPath;
	int pathIndex;
	Army ejercito;
	Army.WarriorCommand actualCommand;
	Vector2 commandTargetPosition;
	enum WarriorState{ death, performingAction, waiting, MAX };
	WarriorState state;
	
	Vector< GameObject > actualSight;
	
	final static int RIGHT = 0;
	final static int UPRIGHT = 1;
	final static int UP = 2;
	final static int UPLEFT = 3;
	final static int LEFT = 4;
	final static int DOWNLEFT = 5;
	final static int DOWN = 6;
	final static int DOWNRIGHT = 7;
	final static int DEATH = 8;
		
	Image[] standImage = new Image[9];
	Image[] walkImage = new Image[8];
	Image[] attackImage = new Image[8];
	
	public Warrior()
	{
		lookAt = new Vector2( 1, 0 );
		speed = 30;
		busyTime = 0;
		attackRadius = 10;
		attackDamage = 10;
		attackTime = 5;
		sightDistance = 100;
		state = WarriorState.waiting;
		waitTime = 0;
		attackTime = 0;
	}
	
	abstract public void loadImages(int t);
	
	public double[] interpolate(double x1, double y1, double x2, double y2){
		
		double scale = 0.1f;
		double[] dirVector;
		dirVector = new double[2]; //direction vector
		dirVector[0]= x2-x1;
		dirVector[1]= y2-y1;
		
		//normalize
		double mag = (double)Math.sqrt(dirVector[0]*dirVector[0]+dirVector[1]*dirVector[1]);
		dirVector[0]=(dirVector[0]/mag)*scale;
		dirVector[1]=(dirVector[1]/mag)*scale;
		
		double[] interpolated;
		interpolated = new double[2];
		interpolated[0]=x1+dirVector[0];
		interpolated[1]=y2+dirVector[1];
		
		return interpolated; 
		
	}
	boolean frame = true;
	public void setOrientation(WarriorAction.Action action)
	{
		try
		{
			int i;
			if( state == WarriorState.death )
				icon = standImage[ Warrior.DEATH ];
			else
			{
				double angle = Math.atan( lookAt.y / lookAt.x );
				if( lookAt.x < 0 )
					angle += Math.PI;
				i = (int) Math.floor( 8 * ( angle + Math.PI / 8 ) / ( 2 * Math.PI ) );
				if( i < 0 )
					i += 8;
				if( i >= 8 )
					i = i % 8;
			
				switch (action){
				
				case WAIT:		
					icon = standImage[ i ];
					break;
					
				case MOVE:
					if(frame)
						icon = walkImage[ i ];
					else
						icon = standImage[ i ];
					frame=!frame;
					
					
					break;
					
				case ATTACKSWORD:
					
				case ATTACKARROW:
					
					icon = attackImage[i];
					
					break;
				
				
				}
			}
		}
		catch(ArrayIndexOutOfBoundsException e)
		{
			System.out.println("Out of bounds exception!");			
		}
	}
	
	public Image getIcon()
	{
		setOrientation(getCurrentAction());
		return icon;
	}
	
	abstract public void animate();
	
	//Esta funcion es llamada por Army, se refiere a la mision que debe seguir el guerrero
	abstract public void order( Army.WarriorCommand command, Vector2 targetPosition );

	//Esta funcion es llamada por GameLogic, y se refiere al turno que tiene el guerrero de pensar y realizar
	//su accion. El parametro que devuelve es la accion en concreto que realizara.
	abstract public WarriorAction actionTurn();
	
	//Si el guerrero quiere moverse a una posicion y hay un obstaculo (ej. otro guerrero), game logic debe reportarle
	//su nueva posicion
	public void setPosition( Vector2 newPosition )
	{
		position = newPosition;
	}
	
	//Ya sea GameLogic o Army quien reporta el dagno que se le aplico a este guerrero
	public void setDamage( int damage )
	{
		hp -= damage;
		if ( hp <= 0 )
			death();
	}
	
	//Que pasa cuando se muere
	private void death()
	{
		state = WarriorState.death;
		ejercito.warriorDeath( this );
	}
	
	//Recive la informacion a su alrededor, esperaria que GameLogic sea quien reporta esto
	public void setActualSight( Vector< GameObject > reportedSight )
	{
		actualSight = reportedSight;
	}
	
	public WarriorState GetState()
	{
		return state;
	}

	   
   public WarriorAction.Action getCurrentAction()
   {
	   return currentAction;
   }	
}
